
#include <fstream>  // NOLINT(readability/streams)
#include <string>
#include <stdio.h>
#include <iostream>

#include "glog/logging.h"
#include "google/protobuf/text_format.h"
#include "stdint.h"

#include "caffe/proto/caffe.pb.h"
#include "caffe/util/format.hpp"
#include "caffe/util/math_functions.hpp"

using namespace std;

#ifdef USE_LEVELDB
#include "leveldb/db.h"

uint32_t swap_endian(uint32_t val) {
	val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
	return (val << 16) | (val >> 16);
}

// db_filename: input leveldb file
// txt_filename: output text file
void view_dataset(const char* db_filename, const char* txt_filename) {
	
	// Open leveldb
	leveldb::DB* db;
	leveldb::Options options;
	options.create_if_missing = false;
	options.error_if_exists = false;	
	leveldb::Status status = leveldb::DB::Open(
		options, db_filename, &db);
	CHECK(status.ok()) << "Failed to open leveldb " << db_filename;
	
	std::ofstream file;
	std::string filepath = txt_filename;
	CHECK(!filepath.empty()) << "Output text file path is empty ";

	file.open(filepath);
	file << "<table>";

	auto it = db->NewIterator(leveldb::ReadOptions());	
	it->SeekToFirst();
	int i = 0;
	while (it->Valid())
	{
		file << "<tr><td>";
		file << it->key().data();
		file << "</td><td>";
		std::stringstream ss;
		for (int i = 0; i < it->value().size(); i++)
		{
			ss << std::hex << (int)it->value().data()[i];
		}
		std::string s = ss.str();
		file << s;
		file << "</td></tr>";
		
		it->Next();
	}

	file << "</table>";
	file.flush();	
	file.close();

	std::cout << "\nFile Saved to " << filepath << "\n";

	delete it;
	delete db;
}

int main(int argc, char** argv) {
	if (argc != 3) {
		printf("This tool requires the db and text file paths\n"
			"Usage:\n"
			"leveldb_viewer.exe  input_db_file  output_text_file\n");
	}
	else {
		google::InitGoogleLogging(argv[0]);
		view_dataset(argv[1],argv[2]);
	}

	getchar();

	return 0;
}
#else
int main(int argc, char** argv) {
	LOG(FATAL) << "This example requires LevelDB; compile with USE_LEVELDB.";
}
#endif  // USE_LEVELDB
